﻿/*+========================================================
File:		Bill.cpp
Sumary:		Hiện thực hóa các phương thức của lớp CBill
========================================================+*/

#include "Bill.h"
#include "PlayState.h"
#include "StoneFallingPoint.h"
#include "BossTwo.h"
#include "BossTwoPartArm.h"
#include <math.h> 


float cint(float x)
{
	float k;
	if (modff(x, &k) >= 0.5f)
		return x >= 0 ? floor(x) : ceil(x);
	else
		return x < 0 ? ceil(x) : floor(x);
}

float round(float value, unsigned int digits)
{
	float off = pow(10, digits);
	return cint(value * off) / off;
}

CBill::CBill(D3DXVECTOR2 pos, int id, int typeID)
	:CMoveableObject(pos, id, typeID)
{
	m_pResourceManager->GetSprite(ID_SPRITE_BILL_STAND);
	m_pResourceManager->GetSprite(ID_SPRITE_BILL_STAND_FIRE);
	m_pResourceManager->GetSprite(ID_SPRITE_BILL_STAND_ABOVE);
	m_pResourceManager->GetSprite(ID_SPRITE_BILL_FIRE_ABOVE);
	m_pResourceManager->GetSprite(ID_SPRITE_BILL_LAY);
	m_pResourceManager->GetSprite(ID_SPRITE_BILL_RUN);
	m_pResourceManager->GetSprite(ID_SPRITE_BILL_RUN_TOP);
	m_pResourceManager->GetSprite(ID_SPRITE_BILL_RUN_BOT);
	m_pResourceManager->GetSprite(ID_SPRITE_BILL_RUN_FIRE);
	m_pResourceManager->GetSprite(ID_SPRITE_BILL_JUMP);
	m_pResourceManager->GetSprite(ID_SPRITE_BILL_FALL);
	m_pResourceManager->GetSprite(ID_SPRITE_BILL_SWIM_HIDE);
	m_pResourceManager->GetSprite(ID_SPRITE_BILL_SWIM_STAND);
	m_pResourceManager->GetSprite(ID_SPRITE_BILL_SWIM_FIRE);
	m_pResourceManager->GetSprite(ID_SPRITE_BILL_SWIM_LOOK_TOP);
	m_pResourceManager->GetSprite(ID_SPRITE_BILL_SWIM_LOOK_ABOVE);
	m_pResourceManager->GetSprite(ID_SPRITE_BILL_SWIM_GRASS_UP);
	m_pResourceManager->GetSprite(ID_SPRITE_BILL_DYING);
	m_pResourceManager->GetSprite(ID_SPRITE_BILL_DIE);
	m_pTextureBox = m_pResourceManager->GetTexture(ID_TEXTURE_BILL_BOX);
	m_pResourceManager->GetSound(ID_SOUND_CONTRA_FIRE);
	m_pResourceManager->GetSound(ID_SOUND_CONTRA_DEAD);
	m_pResourceManager->GetSound(ID_SOUND_GUN_UP);
	m_bIsRight = true;
	m_direction = Direction::None;
	m_status = Status::Jump;
	m_bIsImmortal = false;

	m_a.y = GRAVITY;
	m_a.x = 0.0f;

	m_timeChange = 0.0f;

	m_nLife = g_nLives;
	m_bIsChangeScene = false;
	m_bCSJump = false;
	m_bInitPS = false;
	m_bIsResetPS = false;
	m_fTimeDestroy = 1.0f;

	m_pGun = new CGun(g_nCurrentBullet);
	//Load trước sprite của Bill
}

CBill::~CBill()
{
	if (m_pGun)
		delete m_pGun;
}

void CBill::Update(float timeFrame)
{

	if (!m_bIsLive)
		return;

	UpdateStateChanging(timeFrame);
	UpdateKeyboard(timeFrame);

	UpdateAnimation(timeFrame);

	m_pSprite->Update(timeFrame);
	UpdateBox(timeFrame);
}

void CBill::UpdateBox(float timeFrame)
{
	// Gọt box của bill lại, tính theo chiều bill quay mặt qua phải.
	switch (m_status)
	{
	case Ground:
	case Fall:
		m_box.width = 28.0f;
		m_box.height = 68.0f;
		m_box.x = m_pos.x - m_pSprite->GetWidth() / 2.0f + 12.0f;
		m_box.y = m_pos.y - m_pSprite->GetHeight() / 2.0f + m_box.height;
		break;
	case Jump:
		m_box.width = 34.0f;
		m_box.height = 42.0f;
		m_box.x = m_pos.x - m_pSprite->GetWidth() / 2.0f + 18.0f;
		m_box.y = m_pos.y - m_pSprite->GetHeight() / 2.0f + m_box.height;
		break;
	case Lay:
		m_box.width = 58.0f;
		m_box.height = 22.0f;
		m_box.x = m_pos.x - m_pSprite->GetWidth() / 2.0f + 2.0f;
		m_box.y = m_pos.y - m_pSprite->GetHeight() / 2.0f + m_box.height;
		break;
	case Swim:
	case GrassUp:
		m_box.width = 30.0f;
		m_box.height = 28.0f;
		m_box.x = m_pos.x - m_pSprite->GetWidth() / 2.0f + 22.0f;
		m_box.y = m_pos.y - m_pSprite->GetHeight() / 2.0f + m_box.height;
		break;
	case Die:
		m_box.width = 66.0f;
		m_box.height = 22.0f;
		m_box.x = m_pos.x - m_pSprite->GetWidth() / 2.0f;
		m_box.y = m_pos.y - m_pSprite->GetHeight() / 2.0f + m_box.height;
		break;
	case Dying:
		m_box.width = 0;
		m_box.height = 0;
		m_box.x = 0;
		m_box.y = 0;
		break;
	}

	// Đảo vị trí x của box lại.
	if (!m_bIsRight)
	{
		float x = m_box.x - (m_pos.x - m_pSprite->GetWidth() / 2.0f);
		m_box.x = m_pos.x + m_pSprite->GetWidth() / 2.0f - x - m_box.width;
	}

	m_box.vX = m_v.x;
	m_box.vY = m_v.y;
}

void CBill::UpdateKeyboard(float timeFrame)
{
	CInput* input = CInput::GetInstance();
	if (!m_bIsChangeScene)
	{
		if (input->IsKeyPress(DIK_1))
		{
			int nextBulletId = m_pGun->GetCurBulletType();
			nextBulletId++;
			if (nextBulletId > ID_L_BULLET)
				nextBulletId = ID_R_BULLET;

			m_pGun->SetCurBulletType(nextBulletId);
		}
		if (input->IsKeyPress(DIK_I))
		{
			if (m_cheatImmortal)
				m_cheatImmortal = false;
			else
				m_cheatImmortal = true;
		}
		if (input->IsKeyPress(DIK_0))
		{
			g_nLives = 30;

		}
		if (input->IsKeyPress(DIK_9))
		{
			g_nLives = 4;

		}
	}

	
	if (m_status == Status::Die || m_status == Status::Dying)
		return;

	if (input->IsKeyDown(DIK_RIGHT) && input->IsKeyDown(DIK_UP))
	{
		m_bIsRight = true;
		m_direction = Direction::Top;
		m_v.x = BILL_SPEED_X;

		m_pGun->SetBulletAngle(45.0f);
	}
	else if (input->IsKeyDown(DIK_RIGHT) && input->IsKeyDown(DIK_DOWN))
	{
		m_bIsRight = true;
		m_direction = Direction::Bot;
		m_v.x = BILL_SPEED_X;

		m_pGun->SetBulletAngle(-45.0f);
	}
	else if (input->IsKeyDown(DIK_LEFT) && input->IsKeyDown(DIK_UP))
	{
		m_bIsRight = false;
		m_direction = Direction::Top;
		m_v.x = -BILL_SPEED_X;

		m_pGun->SetBulletAngle(135.0f);
	}
	else if (input->IsKeyDown(DIK_LEFT) && input->IsKeyDown(DIK_DOWN))
	{
		m_bIsRight = false;
		m_direction = Direction::Bot;
		m_v.x = -BILL_SPEED_X;

		m_pGun->SetBulletAngle(-135.0f);
	}
	else if (input->IsKeyDown(DIK_RIGHT))
	{
		m_bIsRight = true;
		m_direction = Direction::Forward;
		m_v.x = BILL_SPEED_X;

		m_pGun->SetBulletAngle(0.0f);
	}
	else if (input->IsKeyDown(DIK_LEFT))
	{
		m_bIsRight = false;
		m_direction = Direction::Forward;
		m_v.x = -BILL_SPEED_X;

		m_pGun->SetBulletAngle(180.0f);
	}
	else if (input->IsKeyDown(DIK_UP))
	{
		m_direction = Direction::Up;
		m_v.x = 0.0f;

		m_pGun->SetBulletAngle(90.0f);
	}
	else if (input->IsKeyDown(DIK_DOWN))
	{
		m_direction = Direction::Down;

		if (m_status == Status::Ground)
			m_status = Status::Lay;

		m_v.x = 0.0f;

		if (m_status == Status::Jump)
		{
			m_pGun->SetBulletAngle(-90.0f);
		}
		else
		{
			if (m_bIsRight)
				m_pGun->SetBulletAngle(0.0f);
			else
				m_pGun->SetBulletAngle(180.0f);
		}
	}
	else
	{
		if (!m_bIsChangeScene)
		{
			m_direction = Direction::None;
			m_v.x = 0.0f;

			if (m_bIsRight)
				m_pGun->SetBulletAngle(0.0f);
			else
				m_pGun->SetBulletAngle(180.0f);
		}
		else
		{
			if (g_nCurentLvl == ID_LEVEL1 || g_nCurentLvl == ID_LEVEL3)
			{
				if (!m_bCSJump)
				{
					if (m_status == Status::Lay)
					{
						if (m_bCanFall)
						{
							m_status = Status::Fall;
							m_pos.y -= 2;
						}
					}
					else if (m_status == Status::Ground)
					{
						m_status = Status::Jump;
						m_v.y = BILL_SPEED_Y;
						m_bCSJump = true;
					}
				}
				m_bIsRight = true;
				m_direction = Direction::Forward;
				m_v.x = BILL_SPEED_X;

				return;
			}
			else if (g_nCurentLvl == ID_LEVEL2)
			{
				if (m_pos.x > 640 / 2)
				{
					m_bIsRight = false;
					m_direction = Direction::Forward;
					m_v.x = -BILL_SPEED_X;
					
				}
				if (m_pos.x < 640 / 2)
				{
					m_bIsRight = true;
					m_direction = Direction::Forward;
					m_v.x = BILL_SPEED_X;
				}
				if (m_pos.x < 640 / 2)
				{
					if (!m_bCSJump)
					{
						if (m_status == Status::Lay)
						{
							if (m_bCanFall)
							{
								m_status = Status::Fall;
								m_pos.y -= 2;
							}
						}
						else if (m_status == Status::Ground)
						{
							m_status = Status::Jump;
							m_v.y = BILL_SPEED_Y;
							m_bCSJump = true;
						}
					}
				}
			}
			
		}

	}

	if (input->IsKeyPress(DIK_X))
	{
		if (m_status == Status::Lay)
		{
			if (m_bCanFall)
			{
				m_status = Status::Fall;
				m_pos.y -= 2;
			}
		}
		else if (m_status == Status::Ground)
		{
			m_status = Status::Jump;
			m_v.y = BILL_SPEED_Y;

		}
	}


	// Xử lí bắn đạn.
	if (m_pGun->GetCurBulletType() == ID_M_BULLET && !m_bIsFiring)
	{
		// Trường hợp là đạn M. Có thể bắn giữ phím.
		if (input->IsKeyDown(DIK_Z))
		{
			Fire();
		}
	}
	else
	{
		// Trường hợp các loại đạn khác, ko thể bắn bằng cách giữ phím.
		if (input->IsKeyPress(DIK_Z))
		{
			Fire();
		}
	}
}

void CBill::UpdateAnimation(float timeFrame)
{
	switch (m_status)
	{
	case GrassUp:
		m_pSprite = m_pResourceManager->GetSprite(ID_SPRITE_BILL_SWIM_GRASS_UP);
		break;
	case Dying:
		m_pSprite = m_pResourceManager->GetSprite(ID_SPRITE_BILL_DYING);
		break;
	case Die:
		m_pSprite = m_pResourceManager->GetSprite(ID_SPRITE_BILL_DIE);
		break;
	case Ground:					// Animation khi đứng trên đất.
		if (!m_bIsFiring)
		{
			switch (m_direction)
			{
			case None:
				m_pSprite = m_pResourceManager->GetSprite(ID_SPRITE_BILL_STAND);
				break;
			case Forward:
				m_pSprite = m_pResourceManager->GetSprite(ID_SPRITE_BILL_RUN);
				break;
			case Up:
				m_pSprite = m_pResourceManager->GetSprite(ID_SPRITE_BILL_STAND_ABOVE);
				break;
			case Top:
				m_pSprite = m_pResourceManager->GetSprite(ID_SPRITE_BILL_RUN_TOP);
				break;
			case Bot:
				m_pSprite = m_pResourceManager->GetSprite(ID_SPRITE_BILL_RUN_BOT);
				break;
			}
		}
		else
		{
			switch (m_direction)
			{
			case None:
				m_pSprite = m_pResourceManager->GetSprite(ID_SPRITE_BILL_STAND_FIRE);
				break;
			case Forward:
				m_pSprite = m_pResourceManager->GetSprite(ID_SPRITE_BILL_RUN_FIRE);
				break;
			case Up:
				m_pSprite = m_pResourceManager->GetSprite(ID_SPRITE_BILL_STAND_ABOVE);
				break;
			case Top:
				m_pSprite = m_pResourceManager->GetSprite(ID_SPRITE_BILL_RUN_TOP);
				break;
			case Bot:
				m_pSprite = m_pResourceManager->GetSprite(ID_SPRITE_BILL_RUN_BOT);
				break;
			}
		}
		break;
	case Jump:     // Animation khi nhảy.
		m_pSprite = m_pResourceManager->GetSprite(ID_SPRITE_BILL_JUMP);
		break;
	case Lay:      // Animation khi nằm.
		m_pSprite = m_pResourceManager->GetSprite(ID_SPRITE_BILL_LAY);
		break;
	case Fall:     // Animation khi rơi.
		m_pSprite = m_pResourceManager->GetSprite(ID_SPRITE_BILL_FALL);
		break;
	case Swim:     // Animation khi bơi.
		if (!m_bIsFiring)
		{
			switch (m_direction)
			{
			case None:
			case Forward:
			case Up:
			case Top:
			case Bot:
				m_pSprite = m_pResourceManager->GetSprite(ID_SPRITE_BILL_SWIM_STAND);
				break;
			case Down:
				m_pSprite = m_pResourceManager->GetSprite(ID_SPRITE_BILL_SWIM_HIDE);
			}
		}
		else
		{
			switch (m_direction)
			{
			case None:
			case Forward:
				m_pSprite = m_pResourceManager->GetSprite(ID_SPRITE_BILL_SWIM_FIRE);
				break;
			case Up:
				m_pSprite = m_pResourceManager->GetSprite(ID_SPRITE_BILL_SWIM_LOOK_ABOVE);
				break;
			case Top:
				m_pSprite = m_pResourceManager->GetSprite(ID_SPRITE_BILL_SWIM_LOOK_TOP);
				break;
			}
		}
		break;
	}
}

void CBill::UpdateStateChanging(float timeFrame)
{
	if (m_bIsFiring)
	{
		if (m_timeChange < 0.0f)
		{
			m_bIsFiring = false;

			m_timeChange = 0.0f;
		}
		else
		{
			m_timeChange -= timeFrame;
		}
	}

	if (m_status == Status::Dying)
	{
		if (m_timeDie > 0)
		{
			m_timeDie -= timeFrame;
		}
		else
		{
			m_v.x = 0.0f;
			m_timeDie = 0.0f;
			m_timeReset = 1.0f;
			m_status = Status::Die;
		}
	}

	if (m_status == Status::Die)
	{
		if (m_timeReset > 0)
		{
			m_timeReset -= timeFrame;
		}
		else
		{
			m_timeReset = 0.0f;
			this->Reset();
		}
	}

	if (m_bIsImmortal)
	{
		if (m_timeImmortal > 0)
		{
			m_timeImmortal -= timeFrame;
			m_nCount++;
		}
		else
		{
			m_timeImmortal = 0.0f;
			m_bIsImmortal = false;
		}
	}

	if (m_cheatImmortal)
		m_bIsImmortal = true;
}

void CBill::UpdateCollision(vector<CGameObject*> vecGameObjs, float timeFrame)
{
	if (!m_bIsLive)
		return;

	m_nCountCollision = 0;

	float timeCollision = timeFrame;
	float normalx = 0.0f, normaly = 0.0f;

#pragma region Va chạm với boss

	if (!m_bIsImmortal)
	{
		if (CPlayState::m_pObjBoss->IsLive())
		{
			if (CPlayState::m_pObjBoss->GetTypeId() == ID_BOSS_TWO)
			{
				CBossTwoPartArm* leftHead = dynamic_cast<CBossTwo*>(CPlayState::m_pObjBoss)->GetLeftHeadArm();
				CBossTwoPartArm* rightHead = dynamic_cast<CBossTwo*>(CPlayState::m_pObjBoss)->GetRightHeadArm();

				while (leftHead != NULL)
				{
					float timeCollision = CheckCollision(leftHead, normalx, normaly, timeFrame);
					if (timeCollision < timeFrame)
					{
						if (this->Kill())
						{
							m_pos += m_v * timeCollision;
							break;
						}
					}

					leftHead = leftHead->prevPartArm;
				}

				while (rightHead != NULL)
				{
					float timeCollision = CheckCollision(rightHead, normalx, normaly, timeFrame);
					if (timeCollision < timeFrame)
					{
						if (this->Kill())
						{
							m_pos += m_v * timeCollision;
							break;
						}
					}

					rightHead = rightHead->prevPartArm;
				}
			}
		}
	}

#pragma endregion

#pragma region Va chạm với đạn enemy

	if (!m_bIsImmortal)
	{
		timeCollision = timeFrame;
		normalx = 0.0f, normaly = 0.0f;
		CGameObject* bulletCollision = NULL;

		for (int i = 0; i < CPlayState::s_enemyBullets.size(); i++)
		{
			if (CPlayState::s_enemyBullets[i]->IsLive())
			{
				float t = CheckCollision(CPlayState::s_enemyBullets[i], normalx, normaly, timeFrame);

				if (t < timeFrame && t < timeCollision)
				{
					// Tìm đối tượng và thời gian va chạm sớm nhất.
					timeCollision = t;
					bulletCollision = CPlayState::s_enemyBullets[i];
				}
			}
		}


		// Xử lí va chạm với đối tượng đạn sớm nhất.
		if (bulletCollision != NULL)
		{
			if (!(m_status == Status::Swim && m_direction == Direction::Down))
			{
				if (this->Kill())
				{
					m_pos += m_v * timeCollision;
					bulletCollision->Kill();

					return;
				}
			}
		}
	}

#pragma endregion

#pragma region Va chạm với các đối tượng ngoài quadtree

	if (m_status != Status::Dying && m_status != Status::Die)
	{
	timeCollision = timeFrame;
	normalx = 0.0f, normaly = 0.0f;

	CGameObject* toneFly = NULL;


	// Update với các item ngoài quadtree.
	for (int i = 0; i < CPlayState::s_objsOutSideQuadTree.size(); i++)
	{
		if (CPlayState::s_objsOutSideQuadTree[i]->GetTypeId() == ID_ENEMY_EXPLOSION)
			toneFly = CPlayState::s_objsOutSideQuadTree[i];


		float timeCollision = CheckCollision(CPlayState::s_objsOutSideQuadTree[i], normalx, normaly, timeFrame);

		if (timeCollision < timeFrame)
		{
			switch (CPlayState::s_objsOutSideQuadTree[i]->GetTypeId())
			{
			case ID_M_ITEM:
			case ID_F_ITEM:
			case ID_S_ITEM:
			case ID_L_ITEM:
			case ID_R_ITEM:
				m_pSound = m_pResourceManager->GetSound(ID_SOUND_GUN_UP);
				if (m_pSound->IsSoundPlaying())
					m_pSound->Reset();
				else
				{
					m_pSound->Play();
				}
				if (CPlayState::s_objsOutSideQuadTree[i]->GetTypeId() != ID_R_ITEM)
					m_pGun->UpGun(CPlayState::s_objsOutSideQuadTree[i]->GetTypeId());
				CPlayState::s_objsOutSideQuadTree[i]->Kill();
				break;
			case ID_B_ITEM:
				m_bIsImmortal = true;
				m_timeImmortal = 10.0f;
				CPlayState::s_objsOutSideQuadTree[i]->Kill();
				break;
			case ID_EAGLE_ITEM:
				m_bIsDestroyed = true;
				CPlayState::s_objsOutSideQuadTree[i]->Kill();
				break;
			case ID_ENEMY_EXPLOSION:
			case ID_BIG_EXPLOSION:
				if (!m_bIsImmortal)
					if (((CExplosion*)CPlayState::s_objsOutSideQuadTree[i])->IsDamage())
					{
						this->Kill();
					}
				break;
				case ID_BOSS_THREE_CHILD:
					if (!m_bIsImmortal)
						this->Kill();
					break;
			}
		}
	}
	}

#pragma endregion

#pragma region Va chạm với enemy chạy
	timeCollision = timeFrame;
	normalx = 0.0f, normaly = 0.0f;
	if (!m_bIsImmortal)
	{
		// Update với các item ngoài quadtree.
		for (int i = 0; i < MAX_ENEMIES; i++)
		{
			if (CPlayState::s_enemyRun[i]->IsLive())
			{
				float timeCollision = CheckCollision(CPlayState::s_enemyRun[i], normalx, normaly, timeFrame);
				if (timeCollision < timeFrame)
				{
					this->Kill();
				}
			}
		}
	}
#pragma endregion

#pragma region Xử lý hiệu ứng của item Eagle
	if (m_bIsDestroyed)
	{
		if (m_fTimeDestroy > 0)
		{
			m_fTimeDestroy -= timeFrame;
			this->DestroyAll(timeFrame, vecGameObjs);
		}
		else
		{
			m_fTimeDestroy = 0.0f;
			if (!m_bIsResetPS)
			{
				m_bIsResetPS = true;
				CGraphic::GetInstance()->InitPixelShader(HLSL3_PATH);
				m_bIsDestroyed = false;
			}
		}
	}

#pragma endregion

#pragma region Va chạm với các đối tượng trong quadtree

	float topTime, leftTime, rightTime;
	topTime = leftTime = rightTime = timeFrame;
	CGameObject* topObj = NULL;
	CGameObject* leftObj = NULL;
	CGameObject* rightObj = NULL;

	for (int i = 0; i < vecGameObjs.size(); i++)
	{
		CGameObject* gameObj = vecGameObjs[i];
		if (gameObj->IsLive())
		{
			if (gameObj->GetTypeId() == ID_STONE_FALLING_POINT)
				gameObj = dynamic_cast<CStoneFallingPoint*>(gameObj)->GetCurrentStone();


			normalx = 0.0f, normaly = 0.0f;
			float t = CheckCollision(gameObj, normalx, normaly, timeFrame);

			if (t < timeFrame)   // Có xảy ra va chạm.
			{
				switch (gameObj->GetTypeId())
				{
					// Lấy ra các đối tượng có va chạm chiều left, right, top để xử lí sau.
				case ID_GRASS:
					if (normaly == 1 && t < topTime)
					{
						topTime = t;
						topObj = gameObj;
					}
					else if (normalx == -1 && t < leftTime)
					{
						leftTime = t;
						leftObj = gameObj;
					}
					else if (normalx == 1 && t < rightTime)
					{
						rightTime = t;
						rightObj = gameObj;
					}
					break;
				case ID_SBOX:
					if (normalx == -1 && t < leftTime)
					{
						leftTime = t;
						leftObj = gameObj;
					}
					else if (normalx == 1 && t < rightTime)
					{
						rightTime = t;
						rightObj = gameObj;
					}
					break;
				case ID_GRASS_CAN_FALL:
				case ID_BRIDGE:
				case ID_WATER:
				case ID_STONE_FLYING:
					if (normaly == 1 && t < topTime)
					{
						topTime = t;
						topObj = gameObj;
					}
					break;
					// Các đối tượng khác thì xử lí luôn ở đây.
				case ID_ENEMY_SNIPER:
				case ID_ENEMY_SHELTER:
				case ID_ENEMY_MACHINE:
				case ID_FIRE:
				case ID_TANK:
				case ID_BOSS_THREE:
				case ID_BOSS_THREE_CHILD:
				case ID_BOSS_THREE_BULLET:
					if (!m_bIsImmortal)
						this->Kill();
					break;
				case ID_STONE_FALLING:
					//if (normaly == -1 && !m_bIsImmortal)
					//{
					//	this->Kill();
					//	//output_print("Kill\n");
					//}
					if (dynamic_cast<CStoneFalling*>(gameObj)->IsFalling())
					{
						if (!m_bIsImmortal)
							this->Kill();
					}
					break;
				}
			}
		}
	}

	if (topObj != NULL)
		RespondTopGroundCollision(topObj, topTime);
	if (leftObj != NULL)
		RespondLeftGroundCollision(leftObj, leftTime);
	if (rightObj != NULL)
		RespondRightGroundCollision(rightObj, rightTime);

#pragma endregion

	// Update vị trí.
	m_pos += m_v * timeFrame;
	m_v += m_a * timeFrame;

	D3DXVECTOR2 vpPos = CViewport::GetInstance()->GetPosition();
	// Bill ko chạy ngược lại về bên trái đc.
	m_pos.x = m_pos.x - m_pSprite->GetWidth() / 2.0f >= vpPos.x ? m_pos.x : vpPos.x + m_pSprite->GetWidth() / 2.0f;
	// Bill ko chạy ngược lại về bên phải đc.
	if (g_nCurentLvl == ID_LEVEL2)
	{
		if (m_pos.x + m_pSprite->GetWidth() / 2.0f >= vpPos.x + SCREEN_WIDTH)
			m_pos.x = vpPos.x + SCREEN_WIDTH - m_pSprite->GetWidth() / 2.0f;
	}
	// Bill chết khi rơi khỏi màn hình.
	if (m_pos.y - m_pSprite->GetHeight() / 2.0f < vpPos.y - SCREEN_HEIGHT - 20.0f)
		this->Kill();

	// Rơi khi đi hết đất, cầu.
	if (m_nCountCollision == 0)
	{
		if (m_status == Status::Ground)
		{
			m_status = Status::Fall;
			if (m_bIsRight)
				m_v.x = BILL_SPEED_X;
			else
				m_v.x = -BILL_SPEED_X;
		}
	}
}

void CBill::RespondTopGroundCollision(CGameObject* gameObject, float topTime)
{
	switch (gameObject->GetTypeId())
	{
	case ID_GRASS:
		if (m_status == Status::Swim)
		{
			// Leo lên bờ.
			m_status = Status::GrassUp;
			if (m_bIsRight)
				m_pos.x += 5;
			else
				m_pos.x -= 5;
		}
		else if (m_status != Status::Die)
			m_status = Status::Ground;

		m_pos.y += m_v.y * topTime;
		m_pos.y += 0.1f;
		m_v.y = 0.0f;
		m_bCanFall = false;
		m_nCountCollision++;
		break;
	case ID_GRASS_CAN_FALL:
	case ID_BRIDGE:
		m_pos.y += m_v.y * topTime;
		m_pos.y += 0.1f;
		m_v.y = 0.0f;
		m_bCanFall = true;
		if (m_status != Status::Die)
			m_status = Status::Ground;
		m_nCountCollision++;
		break;
	case ID_WATER:
		if (m_status != Status::Die)
		{
			m_pos.y += m_v.y * topTime;
			m_pos.y += 0.1f;
			m_v.y = 0.0f;
			m_bCanFall = false;
			m_status = Status::Swim;
		}
		break;
	case ID_STONE_FLYING:

		if (m_status == Status::Die || m_status == Status::Dying)
			return;
		else
		{
			m_status = Status::Ground;

		m_v.x += ((CMoveableObject*)gameObject)->GetVelocity().x;

		m_pos.y += m_v.y * topTime;
		m_pos.y += 0.1f;
		m_v.y = 0.0f;
		m_bCanFall = false;
		m_nCountCollision++;
		break;
	}
}
}

void CBill::RespondLeftGroundCollision(CGameObject* gameObject, float leftTime)
{
	if (!m_bIsChangeScene)
		if (gameObject->GetTypeId() == ID_SBOX)
		{
		m_v.x = 0.0f;
		}
}

void CBill::RespondRightGroundCollision(CGameObject* gameObject, float rightTime)
{
	if (!m_bIsChangeScene)
		if (gameObject->GetTypeId() == ID_SBOX)
		{
		m_v.x = 0.0f;
		}
}

void CBill::Fire()
{
	D3DXVECTOR2 bulletPos;

	// Tính toán vị trí bắn của viên đạn theo trạng thái và hướng bắn.
	switch (m_status)
	{
	case Ground:
		switch (m_direction)
		{
		case None:
			bulletPos.x = m_pos.x + m_pSprite->GetWidth() / 2.0f - 10;
			bulletPos.y = m_pos.y - 2;
		case Forward:
			bulletPos.x = m_pos.x + m_pSprite->GetWidth() / 2.0f + 4;
			bulletPos.y = m_pos.y;
			break;
		case Up:
			bulletPos.x = m_pos.x + 6;
			bulletPos.y = m_pos.y + m_pSprite->GetHeight() / 2.0f + 4;
			break;
		case Top:
			bulletPos.x = m_pos.x + m_pSprite->GetWidth() / 2.0f - 10;
			bulletPos.y = m_pos.y + m_pSprite->GetHeight() / 2.0f - 20;
			break;
		case Bot:
			bulletPos.x = m_pos.x + m_pSprite->GetWidth() / 2.0f;
			bulletPos.y = m_pos.y - m_pSprite->GetHeight() / 2.0f + 20;
			break;
		}
		break;
	case Jump:
		switch (m_direction)
		{
		case None:
			bulletPos.x = m_pos.x + m_pSprite->GetWidth() / 4.0f;
			bulletPos.y = m_pos.y - m_pSprite->GetHeight() / 4.0f;
			break;
		case Forward:
			bulletPos.x = m_pos.x + m_pSprite->GetWidth() / 4.0f;
			bulletPos.y = m_pos.y - m_pSprite->GetHeight() / 4.0f;
			break;
		case Up:
			bulletPos.x = m_pos.x;
			bulletPos.y = m_pos.y;
			break;
		case Down:
			bulletPos.x = m_pos.x;
			bulletPos.y = m_pos.y - m_pSprite->GetHeight() / 2.0f;
			break;
		case Top:
			bulletPos.x = m_pos.x + m_pSprite->GetWidth() / 4.0f;
			bulletPos.y = m_pos.y;
			break;
		case Bot:
			bulletPos.x = m_pos.x;
			bulletPos.y = m_pos.y - m_pSprite->GetHeight() / 2.0f;
			break;
		}
		break;
	case Lay:
		bulletPos.x = m_pos.x + m_pSprite->GetWidth() / 2.0f;
		bulletPos.y = m_pos.y - 28;
		break;
	case Fall:
		bulletPos.x = m_pos.x;
		bulletPos.y = m_pos.y;
		break;
	case Swim:
		switch (m_direction)
		{
		case None:
		case Forward:
			bulletPos.x = m_pos.x + m_pSprite->GetWidth() / 4.0f + 4.0f;
			bulletPos.y = m_pos.y - m_pSprite->GetHeight() / 2.0f + 8.0f;
			break;
		case Up:
			bulletPos.x = m_pos.x + 8.0f;
			bulletPos.y = m_pos.y + 2.0f;
			break;
		case Top:
			bulletPos.x = m_pos.x + m_pSprite->GetWidth() / 2.0f;
			bulletPos.y = m_pos.y - 10.0f;
			break;
		case Down:   // Khi bơi ko bắn ở 2 hướng này.
		case Bot:
			return;
		}
		break;
	}

	// Đảo chiều nếu có.
	if (!m_bIsRight)
	{
		bulletPos.x = m_pos.x - (bulletPos.x - m_pos.x);
		m_pGun->SetCharaterDirectionX(-1);
	}
	else
		m_pGun->SetCharaterDirectionX(1);

	if (m_pGun->Fire(bulletPos))
	{
		m_bIsFiring = true;
		m_timeChange = 0.20f;

		m_pSound = m_pResourceManager->GetSound(ID_SOUND_CONTRA_FIRE);
		if (m_pSound->IsSoundPlaying())
			m_pSound->Reset();
		else
		{
			m_pSound->Play();
		}
	}
}

void CBill::Reset()
{
	g_nLives--;
	if (g_nLives < 0) return;
	// Reset lại trạng thái.
	m_bIsRight = true;
	m_direction = Direction::None;
	m_status = Status::Jump;
	m_timeChange = 0.0f;
	m_bIsImmortal = true;
	m_timeImmortal = 5.0f;
	m_nCount = 0;

	m_v.x = 0;
	m_v.y = 0;

	m_pGun->SetCurBulletType(ID_R_BULLET);

	// Reset lại vị trí.
	D3DXVECTOR2 vpPos = CViewport::GetInstance()->GetPosition();
	switch (g_nCurentLvl)
	{
	case ID_LEVEL1:
	case ID_LEVEL3:
		m_pos.x = vpPos.x + 200;
		m_pos.y = vpPos.y - 50;
		break;
	case ID_LEVEL2:
		m_pos.x = vpPos.x + 150;
		m_pos.y = vpPos.y - SCREEN_HEIGHT / 2;
		break ;
	}

}

void CBill::Draw()
{
	if (!m_bIsLive || !m_pSprite)
		return;
	D3DXVECTOR2 pos = CViewport::GetInstance()->TransformMatrix(m_pos);

	if (m_bIsImmortal)
	{
		if (m_nCount % 2 == 0)
		{
			if (m_bIsRight)
				m_pSprite->Draw(pos);
			else
				m_pSprite->DrawFlipX(pos);
		}
	}
	else
	{
		if (m_bIsRight)
			m_pSprite->Draw(pos);
		else
			m_pSprite->DrawFlipX(pos);
	}
}

bool CBill::Kill()
{
	if (m_status == Status::Dying || m_status == Status::Die)
		return false;
	
	m_pSound = m_pResourceManager->GetSound(ID_SOUND_CONTRA_DEAD);
	if (m_pSound->IsSoundPlaying())
		m_pSound->Reset();
	else
	{
		m_pSound->Play();
	}
	if (m_bIsRight)
		m_v.x = -50.0f;
	else
		m_v.x = 50.0f;

	m_v.y = 200.0f;
	m_timeDie = 0.6f;
	//m_curPos = m_pos;
	m_status = Status::Dying;
	return true;
}

void CBill::DestroyAll(float timeFrame, vector<CGameObject*> aCollisionObject)
{
	if (!m_bInitPS)
	{
		m_bInitPS = true;
		CGraphic::GetInstance()->InitPixelShader(HLSL_EAGLE_PATH);
	}

	for (int i = 0; i < aCollisionObject.size(); i++)
	{
		if (aCollisionObject[i]->GetTypeId() != ID_GRASS &&
			aCollisionObject[i]->GetTypeId() != ID_GRASS_CAN_FALL &&
			aCollisionObject[i]->GetTypeId() != ID_SBOX)
		{
			aCollisionObject[i]->Kill();
		}
	}
	for (int i = 0; i < MAX_ENEMIES; i++)
	{
		CPlayState::s_enemyRun[i]->Kill();
	}
	for (int i = 0; i < CPlayState::s_objsOutSideQuadTree.size(); i++)
	{
		if (CPlayState::s_objsOutSideQuadTree[i]->GetTypeId() != ID_EAGLE_ITEM &&
			CPlayState::s_objsOutSideQuadTree[i]->GetTypeId() != ID_M_ITEM &&
			CPlayState::s_objsOutSideQuadTree[i]->GetTypeId() != ID_S_ITEM &&
			CPlayState::s_objsOutSideQuadTree[i]->GetTypeId() != ID_L_ITEM &&
			CPlayState::s_objsOutSideQuadTree[i]->GetTypeId() != ID_R_ITEM &&
			CPlayState::s_objsOutSideQuadTree[i]->GetTypeId() != ID_F_ITEM)
			CPlayState::s_objsOutSideQuadTree[i]->Kill();
	}
}


